package main.javassist.update;

import javassist.*;

public class UpdateClass {
    public static void main(String[] args) throws Exception {

    //创建池对象，获取类，拿到现有的类
    ClassPool pool = ClassPool.getDefault();
    //? 动态类修改后要重新加载，必须使用同一个类加载器，否则报错，可能重复加载
    ClassLoader loader = new Loader(pool);
    Class<?> clazz = loader.loadClass("cn.tedu.hello.HelloWorld");

    CtClass ct = pool.get(clazz.getName());
    CtClass[] paramTypes = {pool.get(String.class.getName())};
    CtMethod method = ct.getDeclaredMethod("hi", paramTypes);

    //修改现有类的方法，进行复制，“篡改”加入自己的代码
    CtMethod newMethod = CtNewMethod.copy(method, ct, null);
    //? 要修改类必须先解冻，没有解冻，不允许修改，会报错
		ct.defrost();    //解冻

    String newMethodName = method.getName()+"lsy";
    //? 怎么把新旧方法绑定，新方法要自动调用旧方法中代码（关键）
		method.setName(newMethodName);

    StringBuilder sbBody = new StringBuilder();
		sbBody.append("{");
		sbBody.append("System.out.println(\"执行前\");");

    //调用自身的方法
		sbBody.append(newMethodName).append("($$);");        //($$)代表所有参数

		sbBody.append("System.out.println(\"执行后\");");
		sbBody.append("}");
		newMethod.setBody(sbBody.toString());
		ct.addMethod(newMethod);

    //重新编译加载
    clazz =ct.toClass();

    //调用
		clazz.getMethod("hi",String .class).

    invoke(clazz.newInstance(), "tony");
}

}
